package com.sdy.usercenter.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sdy.common.model.BizException;
import com.sdy.common.utils.MapUtil;
import com.sdy.usercenter.biz.mapper.SysResourceMapper;
import com.sdy.usercenter.biz.mapper.SysRoleResourceMapper;
import com.sdy.usercenter.biz.model.SysResource;
import com.sdy.usercenter.biz.model.SysRole;
import com.sdy.usercenter.biz.mapper.SysRoleMapper;
import com.sdy.usercenter.biz.model.SysRoleResource;
import com.sdy.usercenter.biz.model.SysUserRole;
import com.sdy.usercenter.biz.model.vo.RoleAuthResPack;
import com.sdy.usercenter.biz.service.SysRoleService;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import com.sdy.usercenter.biz.service.SysUserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2019-06-14
 */
@Slf4j
@Service
public class SysRoleServiceImpl extends BaseServiceImpl<SysRole> implements SysRoleService {
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;
    @Autowired
    private SysResourceMapper sysResourceMapper;

    @Override
    public void addUsers(List<Integer> userIdList, Integer roleId) {
        Date now = new Date();
        for (Integer userId : userIdList) {
            SysUserRole sysUserRole = new SysUserRole()
                    .setRoleId(roleId)
                    .setUserId(userId)
                    .setCreateTime(now);
            sysUserRoleService.save(sysUserRole);
        }
    }

    @Override
    public void removeUsers(List<Integer> userIdList, Integer roleId) {
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>()
                .eq("role_id", roleId)
                .in("user_id", userIdList)
        );
    }

    @SuppressWarnings("unchecked")
    @Override
    public void updateAuth(Integer roleId, List<RoleAuthResPack> roleAuthResPackList) throws BizException {
        List<Integer> resIdList = new ArrayList<>();
        List<Integer> toRetainAppResIdList = new ArrayList<>();
        if (!roleAuthResPackList.isEmpty()) {
            // 加入app资源
            List<SysResource> appResource = sysResourceMapper.selectList(new LambdaQueryWrapper<SysResource>()
                    .in(SysResource::getCode, roleAuthResPackList.stream().map(RoleAuthResPack::getAppCode).collect(Collectors.toList())));
            toRetainAppResIdList = appResource.stream().map(SysResource::getId).collect(Collectors.toList());
            resIdList.addAll(toRetainAppResIdList);
            // 加入默认资源
            if (!toRetainAppResIdList.isEmpty()) {
                HashSet<String> defaultCodeSet = new HashSet<>();
                roleAuthResPackList.stream().filter(item -> item.getResIdList() == null).forEach(item -> {
                    defaultCodeSet.add(item.getAppCode());
                });
                List<Integer> defaultIdList = appResource.stream()
                        .filter(item -> defaultCodeSet.contains(item.getCode()))
                        .map(SysResource::getId)
                        .collect(Collectors.toList());
                if (!defaultIdList.isEmpty()) {
                    List<SysRoleResource> defaultRoleResList = sysRoleResourceMapper.selectList(new LambdaQueryWrapper<SysRoleResource>()
                            .in(SysRoleResource::getRootResourceId, defaultIdList)
                            .eq(SysRoleResource::getRoleId, roleId)
                            .orderByAsc(SysRoleResource::getRootResourceId, SysRoleResource::getSort, SysRoleResource::getId));
                    resIdList.addAll(defaultRoleResList.stream().map(SysRoleResource::getResourceId).collect(Collectors.toList()));
                }
            }
            // 加入选择的资源
            roleAuthResPackList.stream().filter(item -> item.getResIdList() != null).forEach(item -> resIdList.addAll(item.getResIdList()));
        }
        // 删除没有权限的app资源
        sysRoleResourceMapper.delete(new LambdaQueryWrapper<SysRoleResource>().eq(SysRoleResource::getRoleId, roleId)
                .notIn(!toRetainAppResIdList.isEmpty(), SysRoleResource::getRootResourceId, toRetainAppResIdList));
        // 原有资源
        List<SysRoleResource> roleResList = sysRoleResourceMapper.selectList(new LambdaQueryWrapper<SysRoleResource>()
                .eq(SysRoleResource::getRoleId, roleId)
                .orderByAsc(SysRoleResource::getRootResourceId, SysRoleResource::getSort, SysRoleResource::getId));
        List<Integer> originResIdList = roleResList.stream().map(SysRoleResource::getResourceId).collect(Collectors.toList());
        // 新增资源
//        List<Integer> newResIdList = resIdList.stream().filter(item -> !originResIdList.contains(item)).collect(Collectors.toList());
        List<Integer> newResIdList = resIdList.stream().distinct().collect(Collectors.toList());
        // 删除资源
//        List<Integer> delResIdList = originResIdList.stream().filter(item -> !resIdList.contains(item)).collect(Collectors.toList());
        List<Integer> delResIdList = originResIdList;

        // 删除多余角色资源
        if (!delResIdList.isEmpty()) {
            sysRoleResourceMapper.delete(new LambdaQueryWrapper<SysRoleResource>()
                    .eq(SysRoleResource::getRoleId, roleId)
                    .in(SysRoleResource::getResourceId, delResIdList));
        }
        // 增加新增角色资源
        if (!newResIdList.isEmpty()) {
            AtomicInteger sort = new AtomicInteger(0);
            List<SysResource> newResList = sysResourceMapper.selectList(new LambdaQueryWrapper<SysResource>().in(SysResource::getId, newResIdList));
            Map<Integer, SysResource> rootResIdMap = MapUtil.collectionToMap(newResList, SysResource::getId);
            List<SysRoleResource> toSaveList = newResIdList
                    .stream()
                    .map(item -> new SysRoleResource()
                            .setRootResourceId(rootResIdMap.get(item).getRootId())
                            .setRoleId(roleId)
                            .setResourceId(item)
                            .setSort(sort.incrementAndGet())
                            .setCreateTime(new Date()))
                    .collect(Collectors.toList());
//            sysRoleResourceService.saveBatch(toSaveList);
            for (SysRoleResource item : toSaveList) {
                sysRoleResourceMapper.insert(item);
            }
        }
    }

    @Override
    public Integer countUserByRole(Integer roleId) {
        return sysUserRoleService.lambdaQuery().eq(SysUserRole::getRoleId, roleId).count();
    }
}
